/////////////////////////////////////////////////////////////////////////////
/*/	
*	Creator:		Joshua C. Rouzer and Alexander Kahl
*	Title:			LevelManager.cpp
*	Last Edited:	07/15/2013
*	Summary:		
/*/
/////////////////////////////////////////////////////////////////////////////
#include "LevelManager.h"

#include "CSGD_TextureManager.h"
#include "SGD_String.h"
#include "../TinyXML/tinyxml.h"

#include <cassert>

// Instantiate SINGLETON
CLevelManager* CLevelManager::s_pInstance = nullptr;

/////////////////////////////////////////////////////////////////////////////
// Function		: Get Instance
// Return		: An instance of the level manager
// Notes		: A way to use this singleton
/////////////////////////////////////////////////////////////////////////////
CLevelManager* CLevelManager::GetInstance(){
	if( s_pInstance == nullptr )
		s_pInstance = new CLevelManager;

	return s_pInstance;
}
/////////////////////////////////////////////////////////////////////////////
// Function		: Delete Instance
// Notes		: Destroys the instance of the level manager
/////////////////////////////////////////////////////////////////////////////
void CLevelManager::DeleteInstance(){
	delete s_pInstance;
	s_pInstance = nullptr;
}
/////////////////////////////////////////////////////////////////////////////
// Function		: Default Constructor
// Notes		: Provides default values to variables
/////////////////////////////////////////////////////////////////////////////
CLevelManager::CLevelManager(){
	m_nCurrlevel = 0;
	m_vLevels.clear();
	m_nCurrlevel = -1;
}
/////////////////////////////////////////////////////////////////////////////
// Function		: Destructor
// Notes		: Cleans up any dynamically allocated memory
/////////////////////////////////////////////////////////////////////////////
CLevelManager::~CLevelManager(){
	for( unsigned int i = 0; i < m_vLevels.size(); ++i )
		delete m_vLevels[i];
	m_vLevels.clear();
}
/////////////////////////////////////////////////////////////////////////////
// Function		: Load Levels
// Notes		: Loads in all the levels and all the paths and waypoints they contain
/////////////////////////////////////////////////////////////////////////////
bool CLevelManager::LoadLevels(){

	TiXmlDocument doc;

	// Have Var for file? Defined folder?
	if( doc.LoadFile("WorldXML.xml") == false )
		return false;

	// Access root element
	TiXmlElement* pLevels = doc.RootElement();	// Levels

	if( pLevels == nullptr )
		return false;

	m_vLevels.clear();

	// Root's child nodes
	TiXmlElement* pLevel = pLevels->FirstChildElement("Level");

	while( pLevel != nullptr )
	{
		CLevel* level = new CLevel;
		SField field;

		// Gets Image path
		TOSTRINGSTREAM path;
		const char * DefaultPath = "resource/Images/";

		path  << DefaultPath << pLevel->Attribute("FieldImage");
		if( !path.str().empty() )
			// Load texture with that filepath and stores it.
			field.m_nFieldImgID = CSGD_TextureManager::GetInstance()->LoadTexture( path.str().c_str() );

		path.str( _T("") );

		path  << DefaultPath << pLevel->Attribute("BgImage");
		if( !path.str().empty() )
			// Load texture with that filepath and stores it.
			field.m_nBackgroundImgID = CSGD_TextureManager::GetInstance()->LoadTexture( path.str().c_str() );

		pLevel->Attribute( "Width", &field.m_nWidth );
		pLevel->Attribute( "Height", &field.m_nHeight );
		pLevel->Attribute( "BgHeight", &field.m_nBgHeight );
		pLevel->Attribute( "FieldHeight", &field.m_nFieldHeight );
		
		// Set field of level
		level->SetField( field );

		// Declare Paths
		Path* lane;

		// Get Path Element
		TiXmlElement* pPath = pLevel->FirstChildElement( "Path" );
		int PathID, PosX, PosY;

		while( pPath != nullptr )
		{
			lane = new Path;

			pPath->Attribute( "Num", &PathID );

			lane->SetPathID( PathID );

			CWaypoint* waypoint;

			TiXmlElement* pWaypoint = pPath->FirstChildElement( "Waypoint" );

			while( pWaypoint != nullptr )
			{
				waypoint = new CWaypoint;

				waypoint->SetPathID( PathID );

				pWaypoint->Attribute( "PosX", &PosX );
				pWaypoint->Attribute( "PosY", &PosY );

				waypoint->SetPos( (float)PosX, (float)PosY, 0 );

				lane->AddWaypoint( waypoint );

				pWaypoint = pWaypoint->NextSiblingElement( "Waypoint" );
			}

			// Structure Points
			CWaypoint* buildpoint;
			TiXmlElement* pBuildpoint = pPath->FirstChildElement( "Buildpoint" );

			while ( pBuildpoint != nullptr )
			{
				buildpoint = new CWaypoint;

				buildpoint->SetPathID( PathID );

				pBuildpoint->Attribute( "PosX", &PosX );
				pBuildpoint->Attribute( "PosY", &PosY );

				buildpoint->SetPos( (float)PosX, (float)PosY, 0 );

				lane->AddBuildpoint( buildpoint );

				pBuildpoint = pBuildpoint->NextSiblingElement( "Buildpoint" );
			}

			switch ( lane->GetPathID() )
			{
			case 1:
				level->SetPath1( lane );
				break;
			case 2:
				level->SetPath2( lane );
				break;
			case 3:
				level->SetPath3( lane );
				break;
			}

			pPath = pPath->NextSiblingElement("Path");
		}

		m_vLevels.push_back( level );

		pLevel = pLevel->NextSiblingElement("Level");
	}

	// LAST LEVEL always BOSS LEVEL
	m_vLevels[m_vLevels.size()-1]->m_bBossLevel = true;

	return (m_vLevels.size() > 0);
}
/////////////////////////////////////////////////////////////////////////////
// Function		: Get Current Level
// Return		: The level currently loaded
// Notes		: Accessor
/////////////////////////////////////////////////////////////////////////////
CLevel* CLevelManager::GetCurrLevel(){
	if( m_nCurrlevel == -1 )
		return nullptr;
	return m_vLevels[m_nCurrlevel];
}
/////////////////////////////////////////////////////////////////////////////
// Function		: Set Current Level
// Parameters	: level - the new level
// Notes		: Mutator
/////////////////////////////////////////////////////////////////////////////
void CLevelManager::SetCurrLevel(int level){
	SetLevelID(level);
	m_nCurrlevel = level;
}